import logging
import os
import re
import time
import traceback

import colorful
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


class Kuaiji():
    def __init__(self, username='13957015423', password='l13957015423', browser_type='chrome', qq_send=None):
        self.logger_directory = "log"
        if not os.path.exists(self.logger_directory):
            os.makedirs(self.logger_directory)
        self.qq_send = qq_send
        self.username=username
        self.password=password
        self.logger = logging.getLogger("Kuaiji")
        formatter= logging.Formatter(r'[TIME:%(asctime)s][FILE:%(filename)s][LINENO:%(lineno)d] %(message)s')
        self.logger.setLevel(logging.DEBUG)
        logger_filename = "./Kuaiji_username_{}.log".format(username)
        logger_filename = os.path.join(self.logger_directory, logger_filename)
        filer = logging.FileHandler(logger_filename)
        filer.setLevel(logging.DEBUG)
        filer.setFormatter(formatter)
        self.logger.addHandler(filer)
        streamer = logging.StreamHandler()
        streamer.setLevel(logging.DEBUG)
        streamer.setFormatter(formatter)
        self.logger.addHandler(streamer)
        if self.qq_send:
            self.logger.debug = self.wrap_log(self.logger.debug, 'debug')
            self.logger.info = self.wrap_log(self.logger.info, 'info')
            self.logger.error = self.wrap_log(self.logger.error, 'error')





        self.loginUrl = 'https://puser.zjzwfw.gov.cn/sso/newusp.do'
        self.browser_type = browser_type
        if self.browser_type=='360':
            options = webdriver.ChromeOptions()
            options.binary_location=r'C:\Users\zhouq\AppData\Local\360Chrome\Chrome\Application\360chrome.exe'
            self.browser = webdriver.Chrome(r'./chromedriver78.70.exe', options=options)
        elif self.browser_type=='chrome':
            options = Options()
            # prefs= {
            #     "profile.managed_default_content_settings.images":1,
            #     "profile.content_settings.plugin_whitelist.adobe-flash-player":1,
            #     "profile.content_settings.exceptions.plugins.*,*.per_resource.adobe-flash-player":1,
            # }
            prefs = dict()
            prefs['profile.managed_plugins_allowed_for_urls'] = ['http://jxjycwweb.dongao.com/']
            options.add_experimental_option('prefs', prefs)
            self.browser = webdriver.Chrome(chrome_options=options)
        elif self.browser_type == 'qq':
            options = webdriver.ChromeOptions()
            options.binary_location=r'C:\Program Files (x86)\Tencent\QQBrowser\QQBrowser.exe'
            self.browser = webdriver.Chrome(r'./chromedriver70.exe', options=options)
        elif self.browser_type == 'firefox':
            self.browser = webdriver.Firefox()
        elif self.browser_type == 'edge':
            self.browser = webdriver.Edge()
        self.studyUrl = 'http://jxjy.czt.zj.gov.cn/front/gosignup.html'
        
    
    def wrap_log(self, func, level:str):
        def f(*args, **kwargs):
            if self.qq_send:
                self.qq_send(*args, **kwargs)
            return func(*args, **kwargs)
        return f



    def login(self):
        self.browser.get(self.loginUrl)
        username_input = self.browser.find_element_by_xpath('//input[@id="loginname"]')
        password_input = self.browser.find_element_by_xpath('//input[@id="loginpwd"]')
        submit_button = self.browser.find_element_by_xpath('//input[@id="submit"]')
        username_input.send_keys(self.username)
        password_input.send_keys(self.password)
        submit_button.click()

    def do_video(self):
        '''
        刷视频。假定第一个标签页是课程页面，第二个标签页是视频页面。
        刷到视频标签页自动关闭未知。
        '''
        b = self.browser
        self.logger.info("开始刷视频")
        while True:
            time.sleep(10)
            if len(b.window_handles) == 1:
                self.logger.info("当前课程已经学完，返回课程页面学习下一门课程。")
                b.switch_to_window(b.window_handles[0])
                return
            elif len(b.window_handles) == 2:
                b.switch_to_window(b.window_handles[1])
            else:
                raise Exception("在做视频的时候标签数量既不等于1也不等于2")
            if b.page_source.find(r'<div class="box_head_tip">知识点测试</div>') < 0:
                self.logger.info("没有题目出现，等待10秒钟")
                continue
            self.logger.info("出现题目，尝试做题")
            self.logger.info("等待3秒钟，使题目页面稳定") #题目出来有动画，不等待可能会卡在中间界面
            time.sleep(3)
            multi_select_pattern = r'<p class="multiselect_select">(.*?)value="(?P<value>.*?)"'
            selects = re.finditer(multi_select_pattern, b.page_source) 
            selects_dicts = [v.groupdict() for v in selects]
            selects_values = [v['value'] for v in selects_dicts]
            self.logger.info("发现{num}个选项：{options}".format(
                num=len(selects_values),
                options = ", ".join(selects_values)
            ))
            selects_objs = dict()
            for v in selects_values:
                selects_objs[v] = b.find_element_by_xpath("//p[@class='multiselect_select']/span[@value='{}']".format(v))
            self.logger.info("定位到对应的选项按钮")
            ans_pattern = r'<p class="pop-right-ans"(.*?)value="(?P<answer>.*?)"'
            ret = re.search(ans_pattern,b.page_source)
            ans_dict = ret.groupdict()
            answer = ans_dict['answer']
            self.logger.info("发现本题答案：{}".format(answer))
            for select in answer:
                selects_objs[select].click()
            self.logger.info("已选择答案，准备提交")
            queding = b.find_element_by_xpath('//span[@class="box-sure"]')
            queding.click()
            self.logger.info("已提交")

    def open_course_page(self):
        '''
        登录之后打开课程页面
        '''
        self.browser.get(self.studyUrl)
        self.browser.get(self.studyUrl)
        jixuxuexi=self.browser.find_element_by_link_text("继续学习")
        jixuxuexi.click()
        chacha = self.browser.find_element_by_xpath('//img[@class="tiyan-close"]')
        chacha.click()
        quxuexi = self.browser.find_element_by_link_text("去学习")
        quxuexi.click()
        chacha2 = self.browser.find_element_by_xpath('//img[@class="coverclose"]')
        chacha2.click()
    
    def course_page_to_study_page(self):
        '''
        从课程页面打开学习页面。假定只有一个标签页：课程页面
        '''
        b = self.browser
        b.switch_to_window(b.window_handles[0])
        b.refresh()
        table_pattern = r'<table class="table all">(.*?)</table>'
        WebDriverWait(b, 100).until(lambda b: re.search(table_pattern, b.page_source, re.S))
        # assume only one handle.
        # jixuxuexis = self.browser.find_elements_by_xpath('//a[contains(text(),"继续学习") and @class="operate-a active"]')
        # kaishixuexis = self.browser.find_elements_by_xpath('//a[contains(text(),"开始学习") and @class="operate-a active"]')
        ret = re.search(table_pattern, b.page_source, re.S)
        sub_source = ret.group()
        sub_source = re.sub(r'>[\n\t ]+<', '><', sub_source)
        pattern = r'<tr><td>(?P<xuhao>.*?)</td><td><a(.*?)onclick="(?P<onclick>.*?)"(.*?)>(?P<kechengmingcheng>.*?)</a></td><td>(?P<kechengleibie>.*?)</td><td>(?P<zongxuefen>.*?)</td><td>(?P<yixuexuefen>.*?)</td><td>(?P<xuexishichang>.*?)</td><td>(?P<xuexizhuangtai>.*?)</td>(.*?)</td></tr>'
        search_res = re.finditer(pattern, sub_source, re.S)
        search_dicts = [v.groupdict() for v in search_res]
        for v in search_dicts:
            xuexizhuangtai = v['xuexizhuangtai']
            if xuexizhuangtai.find('已完成')>=0:
                continue
            self.logger.info("找到需要学习的课程：{}".format(v['kechengmingcheng']))
            b.execute_script(v['onclick'])
            b.switch_to_window(b.window_handles[-1])
            beginStudy = b.find_element_by_xpath("//div[@class='beginStudy']")
            beginStudy.click()
            b.close()
            b.switch_to_window(b.window_handles[-1])
            return True
        return None

        jixuxuexis.extend(kaishixuexis)
        if len(jixuxuexis)==0:
            # 没有课程需要学习
            return None
        jixuxuexis[0].click()
        self.browser.switch_to_window(self.browser.window_handles[1])
        return True

    def run(self):
        try:
            self.login()
            self.open_course_page()
            while True:
                ret = self.course_page_to_study_page()
                if ret:
                    self.do_video()
                else:
                    self.logger.info("没有课程需要学习，结束！")
                    return True
        except:
            import time
            source_directory = "Kuaiji-{}-{}".format(
                self.username,
                time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(time.time()))
            )
            source_directory = os.path.join(self.logger_directory, source_directory)
            if not os.path.exists(source_directory):
                os.makedirs(source_directory)
            error_msg = traceback.format_exc()
            try:
                for i,handle in enumerate(self.browser.window_handles):
                    self.browser.switch_to_window(handle)
                    source_file = "handle{}.html".format(i)
                    source_file = os.path.join(source_directory, source_file)
                    with open(source_file, 'w', encoding='utf-8') as f:
                        f.write(self.browser.page_source)
                error_msg = "遇到错误，page_source全部存入{}，错误信息：\n{}".format(
                    source_directory,
                    error_msg
                )
            except:
                save_error_msg = traceback.format_exc()
                error_msg = "遇到错误，page_source部分存入{}，运行错误信息：\n{}\n保存page_source错误信息：\n{}".format(
                    source_directory,
                    error_msg,
                    save_error_msg
                )
            self.logger.error(error_msg)

        

def main(chrome_type='chrome'):
    k = Kuaiji(browser_type=chrome_type)
    k.run()
    return k

if __name__ == '__main__':
    main()
    input("press enter to exit...")
